<?php
if(!defined('BASE_DIR'))die('Cannot access the file !');
/**
 * -+-----------------------------------
 * |PHP Framework
 * |Copyright (c) 2010 jinke.[iblue.cc]
 * |E-mail: mejinke@gmail.com
 * |Date: 2010-04-24
 * -+-----------------------------------
 *
 * 系统高级model模型
 * 主要处理表单验证
 * @author jinke
 */
class AdvModel extends Base
{
	/**
	 * 数据库操作类实例
	 * @var object
	 */
	protected $_db;
	
	/**
	 * 主库连接
	 * @var object
	 */
	protected $master_db = null;
	
	protected $_dbType = MODEL_DB_TYPE_MYSQL;
	/**
	 * 数据库名称
	 * @var string
	 */
	protected  $_dbName	= '';
	

	/**
	 * 将要操作的表名称
	 * @var string
	 */
	protected $_tableName = '';

	/**
	 * 表主键
	 * @var string
	 */
	protected $_pk;

	/**
	 * 主键值
	 * @var string
	 */
	protected $_pkValue = '';

	/**
	 * 字段
	 * @var array
	 */
	public $_fields = array();

	/**
	 * 字段映射
	 * @var array
	 */
	protected $_map = array();

	/**
	 * 验证列表
	 * @var array
	 */
	protected $_validate = array();


	/**
	 * 验证数据，数据不正确时处理方式
	 * 是否直接弹出错误信息
	 * @var bool
	 */
	protected $_valiAlert = true;

	/**
	 * 验证数据，需要验证总数
	 * @var int
	 */
	protected $_valiSum = 0;

	/**
	 * 验证成功数
	 * @var int
	 */
	protected $_valiSuccess = 0;

	/**
	 * 表单临时数据
	 * @var array
	 */
    protected $_formData = array();

	/**
	 * 处理过的表单数据
	 * @var array
	 */
	public $_data = array();


	/**
	 * 构造函数 初始化
	 * @access public
	 */
	public function __construct()
	{

		Debug::initClass('AdvModel.class.php');
		
	}

	/**
	 * __set 魔术方法，设置属性值
	 * @access public
	 * @param string $name	属性名称
	 * @param mixed	$value	值
	 * @return void
	 */
	public function __set($name,$value)
	{
		if(isset($this->$name))
			$this->$name = $value;
	}


	/**
	 * 获取表单提交的数据
	 * @access public
	 * @return object
	 */
	public function getForm(Array $data = null)
	{
		//获取表单数据
		if(empty($data))
			$this->_formData = $_POST;
		else 
			$this->_formData = $data;

		//验证数据
		$this->validateFormData();

		//开始检测字段缓存
		$this->cacheFields();


		//过滤表单提交的数据
		if(!empty($this->_formData))
			//分析映射
			$this->mapFormData();
			
		return $this;

	}

	/**
	 * 删除资料
	 * @access	public
	 * @param	string	$key	键名称
	 * @return	void
	 */
	public function delData($key)
	{
		if(isset($this->_data[$key]))
			unset($this->_data[$key]);
	}



	/**
     * 分析字段映射
	 * @access	private
	 * @return	void
	 */
	private function mapFormData()
	{
		$tep = array();
		if(empty($this->_map))
			$tep = $this->_formData;
		else
		{
			//获取表单数组的KEY
			$form_keys = array_keys($this->_formData);

			//获取手动映射的KEY
			$map_key = array_keys($this->_map);

			for($i=0;$i<count($form_keys);$i++)
			{

				//每一个FORM key 都在 map 中的key对比
				$flag=false;
				for($j=0;$j<count($map_key);$j++)
				{

					if($form_keys[$i] == $map_key[$j])
					{
						$flag=true;
						$tep[$this->_map[$map_key[$j]]]= $this->_formData[$form_keys[$i]];
					}
				}
				//单次对比结束
				if(!$flag)
					$tep[$form_keys[$i]]=$this->_formData[$form_keys[$i]];
			}
		}
		$this->_data = $tep;

		//过滤数据字段
		$this->checkField();
	}




	/**
     * 分析过滤数据的方式
	 * @access	private
	 * @return	void
	 */
	private function checkField()
	{
		//如果自定义字段为空，则使用缓存字段
		if(empty($this->_fields))
		{
			$file=TEMP_DIR.'cache/database/'.$this->_dbName.'/fields/'.$this->_tableName.'.php';
			//检测缓存文件是否存在
			if(is_file($file))
				$field_keys =  require $file;
            else
				return false;
			$this->checkFormData($field_keys);
		}
		//使用自定义字段进行对比过滤
		else
			$this->checkFormData($this->_fields);
	}



	/**
	 * 表单字段对比过滤 最后处理
	 * @access	private
	 * @param	array $field_keys 字段数组
	 * @return	void
	 */
	private function checkFormData(Array $field_keys)
	{

		//获取表单的KEY
		$form_keys = array_keys($this->_data);

		$tep_array = array();
		//分别对每一个表单key 进行分析过滤
		for($i=0;$i<count($form_keys);$i++)
		{
			for($j=0;$j<count($field_keys);$j++)
			{
				//如果匹配到表单key
				if($form_keys[$i] === $field_keys[$j])
				{
					$tep_array[$field_keys[$j]] = $this->_data[$field_keys[$j]];
					$j=count($field_keys);
				}
			}
		}

		$this->_data = $tep_array;

	}






	/**
	 * 缓存数据库字段信息
	 * @access	private
	 * @return	void
	 */
	private function cacheFields()
	{
		//检测是否存在手动定义字段
		if(empty($this->_fields))
		{
			if(empty($this->_tableName))
				return false;
			else
			{
				$cacheFile=TEMP_DIR.'cache/database/'.$this->_dbName.'/fields/';

				//检测缓存文件是否存在
				if(is_file($cacheFile.'.'.$this->_tableName))
					return true;
				//处理字段数组，过滤 pk 主键
				$tepArray=$this->master_db->getFields($this->_tableName);
				$tep = array();
				$html="<?php\n return array(\n\t";
				for($i=0;$i<count($tepArray);$i++)
				{
					//当前字段不是主键
					if($tepArray[$i]!=$this->_pk){
						$tep[]= $tepArray[$i];
						$html.="'".$tepArray[$i]."',\n\t";
					}
				}
				//创建目录
				if(!is_dir($cacheFile))
					Files::mkdirs($cacheFile);
				$html.=");\n?>";
				Files::write($cacheFile.$this->_tableName.'.php',$html);
				return true;
			}
		}
	}


	/**
	 * 验证表单数据完整性 Validate
	 * @access	private
	 * @return	void
	 */
	private function validateFormData()
	{

		if(!empty($this->_validate))
		{
			//检测是否为有效的Validate
			if(!isset($this->_validate['rules']))
				return false;

			//获取验证规则
			$rules = $this->_validate['rules'];

			//获取错误消息
			$message = $this->_validate['message'];

			$vali_keys = array_keys($rules);

			//依次对规则进行分析
			$tep_array = array();
			$required=false;

			foreach($rules as $key=>$val)
			{
				//如果当规则字段存在
				if(isset($this->_formData[$key]))
				{
					//检测是否存在必填规则(required)
					if(strpos($rules[$key],'required')>=0)
						$required=true;

					//将规则转换为数组
					$tep_array = explode(',',$rules[$key]);

					for($i=0;$i<count($tep_array);$i++)
					{
						//获取规则名称及值
						$tep = explode(':',$tep_array[$i]);
						$this->switchValidateFormData($key,$required,strtolower($tep[0]),$tep[1],$message);
					}
				}
			}
		}
	}


	 /**
	 * 验证表单 分析规则 Validate
	 * @access private
	 * @param	string	$key	当前需要验证的字段[key]
	 * @param	string	$required	是否存在required
	 * @param	string	$rules_name	规则名称
	 * @param	mixed	$rules_value	规则值
	 * @param	array		$message	自定义错误信息
	 * @return	void
	 */
	private function switchValidateFormData($key,$required,$rules_name,$rules_value,$message)
	{
		$this->_valiSum++;
		//判断规则，分析结果
		$state = true;

		switch($rules_name)
		{
			//验证 必填
			case 'required':
				if($rules_value=='true')
				{
					if(!isset($this->_formData[$key]) || $this->_formData[$key]=='')
						$state = false;
				}
				break;

			//验证 数字
			case 'number':
				if(!empty($this->_formData[$key]))
				{
					if($rules_value=='true')
					{
						if(!is_numeric($this->_formData[$key]))
							$state = false;
					}
				}
				elseif($required)
					$state = false;
				break;

			//数字小于XX
			case '<':
				if(!empty($this->_formData[$key]))
				{
					if($this->_formData[$key]>$rules_value)
						$state = false;

				}
				elseif($required)
					$state = false;
				break;

			//数字大于XX
			case '>':
				if(!empty($this->_formData[$key]))
				{
					if($this->_formData[$key]<$rules_value)
						$state = false;
				}
				elseif($required)
					$state = false;
				break;


			//验证 是否为正确的email
			case 'email':
				if(!empty($this->_formData[$key]) && $rules_value=='true')
				{
					if (!ereg("^[_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,4}$",$this->_formData[$key]))
					{
						$state = false;
					}
				}
				elseif($required)
					$state = false;
				break;

			//验证 是否为正确的电话号码
			case 'tel':
				if(!empty($this->_formData[$key]) && $rules_value=='true')
				{
					if (!ereg('\d{3}-\d{8}|\d{4}-\d{7}',$this->_formData[$key]))
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			//验证 是否为正确的手机号码
			case 'moblie':
				if(!empty($this->_formData[$key]) && $rules_value=='true')
				{
					if (!ereg('^[1]d{10}',$this->_formData[$key]))
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			//验证 是否为正确的身份证号码
			case 'card':
				if(!empty($this->_formData[$key]) && $rules_value=='true')
				{
					if (!ereg('\d{15}|\d{18}',$this->_formData[$key]))
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			//验证 是否为正确邮政编码
			case 'zip':
				if(!empty($this->_formData[$key]) && $rules_value=='true')
				{
					if (!ereg('[1-9]\d{5}(?!\d)',$this->_formData[$key]))
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			//验证 最小长度
			case 'minlen':
				if(!empty($this->_formData[$key]))
				{
					if(mb_strlen($this->_formData[$key],'utf8')<$rules_value)
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			//验证 最大长度
			case 'maxlen':
				if(!empty($this->_formData[$key]))
				{
					if(mb_strlen($this->_formData[$key],'utf8')>$rules_value)
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			/**
			 *  验证 取值范围在列表中
			 *  例如：in:2|23|9|0
			 *
			 */
			case 'in':
				$flag=0;
				if(!empty($this->_formData[$key]))
				{
					if($tep_array = explode('|',$rules_value))
					{
						for($i=0;$i<count($tep_array);$i++)
						{
							if($this->_formData[$key] == $tep_array[$i])
								$flag++;
						}
					}
					if($flag==0)
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			/**
			 *  验证 取值范围必需不在列表中
			 *  例如：not_in:2|23|9|0
			 *
			 */
			case 'not_in':
				$flag=0;
				if(!empty($this->_formData[$key]))
				{
					if($tep_array = explode('|',$rules_value))
					{
						for($i=0;$i<count($tep_array);$i++)
						{
							if($this->_formData[$key] == $tep_array[$i])
								$flag++;
						}
					}
					if($flag>0)
						$state = false;
				}
				elseif($required)
					$state = false;
				break;

			//验证与指定的字段值是否相同
			case 'confirm':
				if(!empty($this->_formData[$key]))
				{
					if($this->_formData[$key]!=$this->_formData[$rules_value])
						$state = false;
				}
				elseif($required)
					$state = false;
				break;
		}

		//没有错误
		if($state)
		{
			$this->_valiSuccess++;
		//检测到错误
		}
		else
		{
			if($this->_valiAlert)
			{
				if(isset($message[$key][$rules_name]))
					alert($message[$key][$rules_name]);
			}
		}

	}
}
?>